package com.test.lucene.index;

import java.io.File;
import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexDeletionPolicy;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockFactory;
import org.apache.lucene.store.SimpleFSLockFactory;
import org.apache.lucene.store.VerifyingLockFactory;

import com.subshell.lucene.indexaccess.IIndexAccessProvider;
import com.subshell.lucene.indexaccess.ILuceneIndexAccessor;
import com.subshell.lucene.indexaccess.impl.IndexAccessProvider;
import com.subshell.lucene.indexaccess.impl.LuceneIndexAccessor;
import com.test.lucene.LuceneException;

/**
 * Singleton class which controls the creation of the index accessor instance.
 * 
 * @author Patrick Kimber
 * 
 */
final class IndexAccessorController {

    /** Delete a commit after this number of seconds. */
    private static final int DELETION_POLICY_SECONDS = 300;

    /** A single instance of the Lucene index accessor. */
    private static ILuceneIndexAccessor instance;

    /**
     * Private, default constructor.
     */
    private IndexAccessorController() {
    }

    /**
     * Get the single instance of the Lucene index accessor.
     * 
     * @param repositoryFolder
     *            The folder containing the Lucene repository.
     * @return The single instance of the Lucene index accessor. *
     * @throws LuceneException
     *             If the index accessor cannot be created.
     * 
     */
    public static synchronized ILuceneIndexAccessor getInstance(
            final File repositoryFolder) throws LuceneException {
        if (instance == null) {
            createIndexAccessor(repositoryFolder);
        }
        return instance;
    }

    /**
     * Close the Lucene index accessor.
     */
    public static void close() {
        instance.close();
        instance = null;
    }

    /**
     * Create a Lucene index accessor.
     * 
     * @param repositoryFolder
     *            The folder containing the Lucene repository.
     * @throws LuceneException
     *             If the index accessor cannot be created.
     */
    private static void createIndexAccessor(final File repositoryFolder)
            throws LuceneException {
        try {
            //LockFactory lf = new NativeFSLockFactory(getLockFolder(repositoryFolder));
            LockFactory lf = new SimpleFSLockFactory(getLockFolder(repositoryFolder));

            // TODO: set these to match your network, and run
            // LockVerifyServer with the same port
//            lf = new VerifyingLockFactory((byte) 0, lf, "10.17.4.10", 8777);
          
            Directory directory = FSDirectory.getDirectory(repositoryFolder, lf);
            directory.getLockFactory().setLockPrefix("thelock");
                                                           
            IndexDeletionPolicy deletionPolicy = new ExpirationTimeDeletionPolicy(
                    directory, DELETION_POLICY_SECONDS);
            IIndexAccessProvider accessProvider = new IndexAccessProvider(
                    directory, new StandardAnalyzer(), deletionPolicy);
            instance = new LuceneIndexAccessor(accessProvider);
            instance.open();
        } catch (IOException e) {
            throw new LuceneException("Cannot create index accessor.", e);
        }
    }

    /**
     * Generate the lock file location from the repository folder.
     * 
     * @param repositoryFolder
     *            The folder containing the Lucene repository.
     * @return The folder for the lock files.
     */
    private static File getLockFolder(final File repositoryFolder) {
        return new File(repositoryFolder, "/lock/");
    }
}
